﻿
using System.Collections.Generic;
using System.Linq;

namespace Anno.DynamicApi
{
    /// <summary>
    /// 接口定义信息
    /// </summary>
    public class ApiInfo
    {
        public ApiInfo(string _Namespace,string _ControllerName)
        { Namespace = _Namespace; ControllerName = _ControllerName; }
        /// <summary>
        /// 命名空间
        /// </summary>
        public string Namespace { get;  }

        /// <summary>
        /// 控制器名称
        /// </summary>
        public string ControllerName { get;  }
        string _KeyWord = "";
        /// <summary>
        /// 接口唯一标识符
        /// </summary>
        public string KeyWord
        {
            get
            {
                //return (Namespace + "_" + ControllerName + "_" + ApiName).Replace(".", "_");
                if (string.IsNullOrWhiteSpace(_KeyWord))
                {
                    _KeyWord = Path;
                }
                return _KeyWord;
            }
        }
        /// <summary>
        /// 接口入参类型名称,动态生成 类时用
        /// </summary>
        public string InputClassName
        {
            get
            {
                var ret = KeyWord + "_Input";
                var comp = ExecutorList?.FirstOrDefault();
                if (comp != null) ret = KeyWord + comp.InputClassName;
                return ret;
            }
        }
        /// <summary>
        /// 接口是否有执行者
        /// </summary>
        public bool HasExecutor { get { return this.ExecutorList?.Count > 0; } }

        /// <summary>
        /// 接口出参类型名称,动态生成 类时用
        /// </summary>
        public string OnputClassName { get { return KeyWord + "_Output"; } }
        //--------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// 接口名称
        /// </summary>
        public string ApiName { get; set; }

        /// <summary>
        ///  获取和设置服务操作响应的协议（如 HTTP）方法。返回结果:   与操作关联的协议方法
        /// </summary>
        public string HttpMethod { get; set; }
        /// <summary>
        /// 用于服务操作的统一资源标识符 (URI) 模板。返回结果: 用于服务操作的 URI 模板。
        /// </summary>
        public string Route { get; set; }
        /// <summary>
        /// 路由
        /// </summary>
        public string BaseRoute { get; set; }
        /// <summary>
        /// 接口是否启用状态 0是 1否
        /// </summary>
        public int Stat { get; set; } = 0;
        /// <summary>
        /// 
        /// </summary>
        public string Path
        {
            get
            {
                var methodName = this.ApiName;
                if (methodName.ToLower().Equals(this.HttpMethod.ToLower()))
                {
                    methodName = "";
                }
                var template = methodName;
                if (!string.IsNullOrEmpty(this.Route))
                {
                    template = this.Route;
                }
                template = (this.BaseRoute.Trim('/') + "/" + template.Trim('/')).TrimEnd('/');
                return $"/{template.Trim('/')}";
            }
        }
        //--------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// 标题/中文名
        /// </summary>
        public string Title { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }

        /// <summary>
        /// 是否支持多执行者同时执行
        /// </summary>
        public bool MultiExecutor { get; set; }
        /// <summary>
        /// 返回结果是否为驼峰命名
        /// </summary>
        public bool IsCamelCaseNames { get; set; } = false;
        //--------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// 接口执行者集合
        /// </summary>
        public List<BaseExecutor> ExecutorList { get; set; }
        ///// <summary>
        ///// 出参信息
        ///// </summary>
        //public List<ApiOutputInfo> ActionOutputList { get; set; }
        public System.Xml.XmlNode XMLNode { get; set; }

        public ApiInfo(System.Xml.XmlNode xmlNode, ControllerInfo controller)
        {
            if (xmlNode == null || controller == null || xmlNode.NodeType == System.Xml.XmlNodeType.Comment)
            {
                return;
            }
            Namespace = controller?.Namespace;
            ControllerName = controller?.ControllerName;

            Init(xmlNode, controller);
        }
        //public void Init(System.Xml.XmlNode apiNode, ControllerInfo controller)
        //{
        //    try
        //    {
        //        if (apiNode == null || controller == null || apiNode.NodeType == System.Xml.XmlNodeType.Comment)
        //        {
        //            return;
        //        }
        //        BaseRoute = PathUtil.GetBaseRoute(controller.RoutePrefix, controller.ControllerName);

        //        ApiName = PubFun.GetXmlNodeAttributeValue(apiNode, "Name").Trim('.');
        //        HttpMethod = PubFun.GetXmlNodeAttributeValue(apiNode, "HttpMethod", "POST").Trim().ToUpper();
        //        Route = PubFun.GetXmlNodeAttributeValue(apiNode, "Route", HttpMethod + "_"+ ApiName);
        //        Title = PubFun.GetXmlNodeAttributeValue(apiNode, "Title", ApiName);
        //        Remark = PubFun.GetXmlNodeAttributeValue(apiNode, "Remark", Title);
        //        MultiExecutor = PubFun.GetXmlNodeAttributeValue(apiNode, "MultiExecutor", "false").ChangeType<bool>();
        //        IsCamelCaseNames = PubFun.GetXmlNodeAttributeValue(apiNode, "IsCamelCaseNames", controller.IsCamelCaseNames.ToString()).ChangeType<bool>();
        //    }
        //    catch { }
        //}
        public string GetHttpMethod()
        {
            if (HttpMethod.Equals("POST", System.StringComparison.OrdinalIgnoreCase))
            {
                return "HttpPost";
            }
            else if (HttpMethod.Equals("GET", System.StringComparison.OrdinalIgnoreCase))
            {
                return "HttpGet";
            }
            else if (HttpMethod.Equals("PUT", System.StringComparison.OrdinalIgnoreCase))
            {
                return "HttpPut";
            }
            else if (HttpMethod.Equals("DELETE", System.StringComparison.OrdinalIgnoreCase))
            {
                return "HttpDelete";
            }
            return "HttpPost";
        }
        /// <summary>
        /// 返回JSON对象
        /// </summary>
        public virtual object JObject
        {
            get
            {
                var dyret = DicAttrs;

                var executorList = new List<object>();
                ExecutorList?.ForEach(ext => executorList.Add(ext.JObject));
                dyret["ExecutorList"] = executorList;

                dyret["HasExecutor"] = HasExecutor;
                dyret["KeyWord"] = KeyWord;
                dyret["RoutePrefix"] = BaseRoute;
                dyret["Namespace"] = Namespace;
                dyret["ControllerName"] = ControllerName;

                return dyret;

                //var executorList = new List<object>();
                //ExecutorList?.ForEach(ext => executorList.Add(ext.JObject));

                //return new
                //{
                //    Name=ApiName,
                //    HttpMethod,
                //    Route,
                //    Title,
                //    Remark,
                //    MultiExecutor,
                //    IsCamelCaseNames,
                //    ExecutorList = executorList,
                //    Stat,

                //    HasExecutor,
                //    KeyWord,
                //    RoutePrefix,
                //    Namespace,
                //    ControllerName,
                //};
            }
        }
        public virtual IDictionary<string, object> DicAttrs
        {
            get
            {
                var ret = new System.Dynamic.ExpandoObject();
                IDictionary<string, object> dyret = ret;

                //var executorList = new List<System.Collections.Generic.IDictionary<string, object>>();
                //ExecutorList?.ForEach(ext => executorList.Add(ext.DicAttrs));

                dyret["Name"] = ApiName;
                dyret["HttpMethod"] = HttpMethod;
                dyret["Route"] = Route;
                dyret["Title"] = Title;
                dyret["Remark"] = Remark;
                dyret["MultiExecutor"] = MultiExecutor;
                dyret["IsCamelCaseNames"] = IsCamelCaseNames;
                dyret["Stat"] = Stat;
                //dyret["ExecutorList"] = executorList;

                return ret;
            }
        }
        public void Init(System.Xml.XmlNode apiNode, ControllerInfo controller)
        {
            try
            {
                XMLNode = apiNode;
                if (apiNode == null || controller == null || apiNode.NodeType == System.Xml.XmlNodeType.Comment)
                {
                    return;
                }
                BaseRoute = PathUtil.GetBaseRoute(controller.RoutePrefix, controller.ControllerName);

                ApiName = PubFun.GetXmlNodeAttributeValue(apiNode, "Name").Trim('.');
                HttpMethod = PubFun.GetXmlNodeAttributeValue(apiNode, "HttpMethod", "POST").Trim().ToUpper();
                Route = PubFun.GetXmlNodeAttributeValue(apiNode, "Route", ApiName);
                Title = PubFun.GetXmlNodeAttributeValue(apiNode, "Title", ApiName);
                Remark = PubFun.GetXmlNodeAttributeValue(apiNode, "Remark", Title);
                MultiExecutor = PubFun.GetXmlNodeAttributeValue(apiNode, "MultiExecutor", "false").ChangeType<bool>();
                IsCamelCaseNames = PubFun.GetXmlNodeAttributeValue(apiNode, "IsCamelCaseNames", controller.IsCamelCaseNames.ToString()).ChangeType<bool>();
                Stat = PubFun.GetXmlNodeAttributeValue(apiNode, "Stat", "1").ChangeType<int>();
            }
            catch { }

            var apiError = "<Api Name=" + ApiName;
            // 获得Executors子节点
            var ExecutorsNode = apiNode.SelectSingleNode("Executors");
            if (ExecutorsNode == null)
            {
                showException(apiError + " 下无 <Executors/>子节点");
            }
            var executorList = ExecutorsNode.ChildNodes;
            if (executorList == null || ExecutorsNode.HasChildNodes==false)
            {
                showException(apiError + " 下无 <Executors><Executor/></Executors>子节点");
            }
            ExecutorList = new List<BaseExecutor>();
            foreach (System.Xml.XmlNode ExecutorNode in executorList)
            {
                #region 2.2.1. Executor
                var msg = "";
                var tacp = getExecutor(apiError, apiNode, ExecutorNode, this, controller, out  msg);
                if (tacp.Item1 == false) showException(msg);
                if (tacp.Item2 == null) continue;

                #endregion

                ExecutorList.Add(tacp.Item2);
            }
        }
        public void InitExecutorList(Newtonsoft.Json.Linq.JArray executorList, ControllerInfo controller)
        {
            var apiError = ApiName;
            // 获得Executors子节点
            if (executorList == null || executorList.Count == 0)
            {
                showException(apiError + "下Executors节点不能为空");
            }
            ExecutorList = new List<BaseExecutor>();
            foreach (var ExecutorNode in executorList)
            {
                #region 2.2.1. Executor
                var msg = "";
                var tacp = getExecutor(apiError, ExecutorNode, this, controller, out msg);
                if (tacp.Item1 == false) showException(msg);
                if (tacp.Item2 == null) continue;

                #endregion

                ExecutorList.Add(tacp.Item2);
            }
        }
        #region getExecutor
        private Tuple<bool, BaseExecutor> getExecutor(string apiError, Newtonsoft.Json.Linq.JToken ExecutorNode, ApiInfo apiInfo, ControllerInfo controller, out string msg)
        {
            msg = "";
            BaseExecutor acp = null;
            #region 2.2.1. Executor
            if (ExecutorNode == null)// 判断等于注释时
            {
                return Tuple.Create(true, acp);
            }
            var pointType = ExecutorNode.Value<string>("ExecType");// jobj.TryGetValue("ExecType",StringComparison.OrdinalIgnoreCase,out var pointType);
            if (pointType.IsNullOrEmpty())
            {
                msg = apiError + " 的 Executor.ExecType属性不能为空";
                return Tuple.Create(false, acp);
            }
            #region SqlTpl
            if (pointType == ExecutorType.SqlTpl.ToString())
            {
                var SqlTpl = new SqlTplExecutor(ExecutorNode, apiInfo);
                if (SqlTpl.Sql.IsNullOrEmpty_())
                {
                    msg = apiError + " SqlTpl 的 <Executor ExecType=SqlTpl 属性不能为空";
                    return Tuple.Create(false, acp);
                }
                if (string.IsNullOrWhiteSpace(SqlTpl.DBName))
                {
                    SqlTpl.DBName = controller.DefaultDBName;
                }
                #region 获得所有Outputs节点
                SqlTpl.OutputList = new List<ApiOutputInfo>();
                var outputInfoList = ExecutorNode.Value<Newtonsoft.Json.Linq.JArray>("OutputList");
                if (outputInfoList == null)
                {
                    msg = apiError + " 下无OutputList子节点";
                    return Tuple.Create(false, acp);
                }
                foreach (var outputNode in outputInfoList)
                {
                    #region OutputInfo
                    var ret = setOutput(SqlTpl, apiError, outputNode, apiInfo, out msg);
                    if (ret == false) return Tuple.Create(false, acp);

                    #endregion
                }
                #endregion

                acp = SqlTpl;
            }
            #endregion
            #region RemoteApi
            else if (pointType == ExecutorType.RemoteApi.ToString())
            {
                var RemoteApi = new RemoteApiExecutor(ExecutorNode, apiInfo);
                if (RemoteApi.BaseUri.IsNullOrEmpty())
                {
                    msg = apiError + " 的 <Executor BaseUri属性不能为空";
                    return Tuple.Create(false, acp);
                }
                acp = RemoteApi;
            }
            #endregion
            #region RemoteWS
            else if (pointType == ExecutorType.RemoteWS.ToString())
            {
                var RemoteWS = new RemoteWSExecutor(ExecutorNode, apiInfo);
                if (RemoteWS.BaseUri.IsNullOrEmpty())
                {
                    msg = apiError + " 的 <Executor BaseUri属性不能为空";
                    return Tuple.Create(false, acp);
                }
                acp = RemoteWS;
            }
            #endregion
            #region LocalDLL
            else if (pointType == ExecutorType.LocalDLL.ToString())
            {
                var LocalDLL = new LocalDLLExecutor(ExecutorNode, apiInfo);
                if (LocalDLL.FullClassName.IsNullOrEmpty())
                {
                    msg = apiError + " 的 <Executor FullClassName属性不能为空";
                    return Tuple.Create(false, acp);
                }
                acp = LocalDLL;
            }
            #endregion
            #region CSScript
            else if (pointType == ExecutorType.CSScript.ToString())
            {
                var csScript = new CSScriptExecutor(ExecutorNode, apiInfo);
                if (csScript.CSScriptCode.IsNullOrEmpty())
                {
                    msg = apiError + " 的 <Executor CSScriptCode属性不能为空";
                    return Tuple.Create(false, acp);
                }
                acp = csScript;
            }
            #endregion

            if (acp.IsNullOrEmpty())
            {
                msg = apiError + " 的 <Executor ExecType= 属性设置有误";
                return Tuple.Create(false, acp);
            }
            #endregion

            #region 2.2.2. 获得执行者所属 Input、Conditions、Executor节点
            acp.ApiInputInfoList = new List<ApiFieldInfo>();
            acp.Conditions = new ExecConditions();
            #region input 入参
            var inputNodeList = ExecutorNode.Value<Newtonsoft.Json.Linq.JArray>("ApiInputInfoList");
            if (inputNodeList != null && inputNodeList.Count > 0)//入参
            {
                foreach (var inputNode in inputNodeList)
                {
                    if (inputNode == null)// 判断等于注释时
                    {
                        continue;
                    }
                    var ret = setInput(acp, apiError, inputNode, apiInfo, out msg);
                    if (ret == false) return Tuple.Create(false, acp);
                }
            }
            #endregion
            #region conditions 调用过滤条件
            var conditiongNode = ExecutorNode.Value<Newtonsoft.Json.Linq.JToken>("Conditions");
            if (conditiongNode != null)
            {
                acp.Conditions.ConditionType = conditiongNode.GetXmlNodeAttributeValue("ConditionType", "AND").ToEnum_<ConditionType>();
                var conditionList = conditiongNode.Value<Newtonsoft.Json.Linq.JArray>("Items");
                if (conditionList != null && conditionList.Count > 0)
                {
                    foreach (var conditionNode in conditionList)
                    {
                        var condition = new ExecCondition(conditionNode);
                        if (condition.FiledPath.IsNullOrEmpty())
                        {
                            msg = apiError + " 的 <Condition FiledPath属性不能为空";
                            return Tuple.Create(false, acp);
                        }
                        if (condition.Operand.IsNullOrEmpty())
                        {
                            msg = apiError + " 的 <Condition Operand属性不能为空";
                            return Tuple.Create(false, acp);
                        }
                        acp.Conditions.Add(condition);
                    }

                }
            }
            #endregion

            #region Executor 下级执行者
            var nextExecutorList = ExecutorNode.Value<Newtonsoft.Json.Linq.JArray>("NextExecutors");
            if (nextExecutorList != null && nextExecutorList.Count > 0)//下级执行者
            {
                foreach (var nextExecutor in nextExecutorList)
                {
                    var tacp = getExecutor(apiError, nextExecutor, apiInfo, controller, out msg);
                    if (tacp.Item1 == false) return Tuple.Create(false, acp);
                    if (tacp.Item2 != null)
                    {
                        if (acp.NextExecutors == null)
                            acp.NextExecutors = new List<BaseExecutor>();
                        acp.NextExecutors.Add(tacp.Item2);
                    }
                }
            }
            #endregion
            #endregion

            return Tuple.Create(true, acp);
        }
        private Tuple<bool, BaseExecutor> getExecutor(string apiError, System.Xml.XmlNode apiNode, System.Xml.XmlNode ExecutorNode, ApiInfo apiInfo, ControllerInfo controller, out string msg)
        {
            msg = "";
            BaseExecutor acp = null;
            #region 2.2.1. Executor
            if (ExecutorNode.NodeType == System.Xml.XmlNodeType.Comment)// 判断等于注释时
            {
                return Tuple.Create(true, acp);
            }
            var pointType = ExecutorNode.GetXmlNodeAttributeValue("ExecType");
            if (pointType.IsNullOrEmpty())
            {
                msg = apiError + " 的 <Executor ExecType属性不能为空";
                return Tuple.Create(false, acp);
            }
            #region SqlTpl
            if (pointType == ExecutorType.SqlTpl.ToString())
            {
                var SqlTpl = new SqlTplExecutor(ExecutorNode, apiInfo);
                if (SqlTpl.Sql.IsNullOrEmpty_())
                {
                    msg = apiError + " SqlTpl 的 <Executor ExecType=SqlTpl 属性不能为空";
                    return Tuple.Create(false, acp);
                }
                if (string.IsNullOrWhiteSpace(SqlTpl.DBName))
                {
                    SqlTpl.DBName = controller.DefaultDBName;
                }
                #region 获得所有Outputs节点
                SqlTpl.OutputList = new List<ApiOutputInfo>();
                var outputInfosNode = ExecutorNode.SelectSingleNode("Outputs");
                if (apiNode != null && outputInfosNode == null)
                {
                    outputInfosNode = apiNode.SelectSingleNode("Outputs");
                }
                if (outputInfosNode == null)
                {
                    outputInfosNode = ExecutorNode.SelectSingleNode("Output");

                    //var lastCMP = apiInfo.ExecutorList.LastOrDefault();
                    //if (lastCMP != null && lastCMP.ExecType == ExecutorType.SqlTpl)
                    if (outputInfosNode == null)
                    {
                        msg = apiError + "<Executor ExecType=SqlTpl 下无 <Outputs/>子节点";
                        return Tuple.Create(false, acp);
                    }
                    else
                    {
                        var ret = setOutput(SqlTpl, apiError, outputInfosNode, apiInfo, out msg);
                        if (ret == false) return Tuple.Create(false, acp);
                    }
                }
                else
                {
                    var outputInfoList = outputInfosNode.ChildNodes;
                    if (outputInfoList == null)
                    {
                        msg = apiError + " 下无 <Output/>子节点";
                        return Tuple.Create(false, acp);
                    }
                    foreach (System.Xml.XmlNode outputNode in outputInfoList)
                    {
                        #region OutputInfo
                        if (outputNode.NodeType == System.Xml.XmlNodeType.Comment)// 判断等于注释时
                        {
                            continue;
                        }
                        var ret = setOutput(SqlTpl, apiError, outputNode, apiInfo, out msg);
                        if (ret == false) return Tuple.Create(false, acp);

                        #endregion
                    }
                }
                #endregion

                acp = SqlTpl;
            }
            #endregion
            #region RemoteApi
            else if (pointType == ExecutorType.RemoteApi.ToString())
            {
                var RemoteApi = new RemoteApiExecutor(ExecutorNode, apiInfo);
                if (RemoteApi.BaseUri.IsNullOrEmpty())
                {
                    msg = apiError + " 的 <Executor BaseUri属性不能为空";
                    return Tuple.Create(false, acp);
                }
                acp = RemoteApi;
            }
            #endregion
            #region RemoteWS
            else if (pointType == ExecutorType.RemoteWS.ToString())
            {
                var RemoteWS = new RemoteWSExecutor(ExecutorNode, apiInfo);
                if (RemoteWS.BaseUri.IsNullOrEmpty())
                {
                    msg = apiError + " 的 <Executor BaseUri属性不能为空";
                    return Tuple.Create(false, acp);
                }
                acp = RemoteWS;
            }
            #endregion
            #region LocalDLL
            else if (pointType == ExecutorType.LocalDLL.ToString())
            {
                var LocalDLL = new LocalDLLExecutor(ExecutorNode, apiInfo);
                if (LocalDLL.FullClassName.IsNullOrEmpty())
                {
                    msg = apiError + " 的 <Executor FullClassName属性不能为空";
                    return Tuple.Create(false, acp);
                }
                acp = LocalDLL;
            }
            #endregion
            #region CSScript
            else if (pointType == ExecutorType.CSScript.ToString())
            {
                var csScript = new CSScriptExecutor(ExecutorNode, apiInfo);
                if (csScript.CSScriptCode.IsNullOrEmpty())
                {
                    msg = apiError + " 的 <Executor CSScriptCode属性不能为空";
                    return Tuple.Create(false, acp);
                }
                acp = csScript;
            }
            #endregion

            if (acp.IsNullOrEmpty())
            {
                msg = apiError + " 的 <Executor ExecType= 属性设置有误";
                return Tuple.Create(false, acp);
            }
            #endregion

            #region 2.2.2. 获得执行者所属 Input、output、conditions、Executor节点
            var parameterList = ExecutorNode.ChildNodes;
            if (parameterList != null)
            {
                acp.ApiInputInfoList = new List<ApiFieldInfo>();
                acp.Conditions = new ExecConditions();
                foreach (System.Xml.XmlNode parameterNode in parameterList)
                {
                    if (parameterNode.NodeType == System.Xml.XmlNodeType.Comment)// 判断等于注释时
                    {
                        continue;
                    }
                    var localName = parameterNode.LocalName.NullToStr();
                    #region input 入参
                    if (localName.Equals("input", StringComparison.OrdinalIgnoreCase))//入参
                    {
                        var ret = setInput(acp, apiError, parameterNode, apiInfo, out msg);
                        if (ret == false) return Tuple.Create(false, acp);
                    }
                    #endregion
                    #region inputs 入参集合
                    else if (localName.Equals("inputs", StringComparison.OrdinalIgnoreCase))//入参集合
                    {
                        var inputList = parameterNode.ChildNodes;
                        if (inputList != null)
                        {
                            foreach (System.Xml.XmlNode inputNode in inputList)
                            {
                                if (inputNode.NodeType == System.Xml.XmlNodeType.Comment)// 判断等于注释时
                                {
                                    continue;
                                }
                                if (inputNode.LocalName.NullToStr().Equals("input", StringComparison.OrdinalIgnoreCase))//入参
                                {
                                    var ret = setInput(acp, apiError, inputNode, apiInfo, out msg);
                                    if (ret == false) return Tuple.Create(false, acp);
                                }
                            }
                        }
                    }
                    #endregion
                    #region output 出参
                    //只有SqlTpl类型的执行者才有出参配置
                    else if (pointType == ExecutorType.SqlTpl.ToString() && localName.Equals("output", StringComparison.OrdinalIgnoreCase))//入参
                    {
                        var ret = setOutput(acp as SqlTplExecutor, apiError, parameterNode, apiInfo, out msg);
                        if (ret == false) return Tuple.Create(false, acp);
                    }
                    #endregion
                    #region conditions 调用过滤条件
                    else if (localName.Equals("conditions", StringComparison.OrdinalIgnoreCase))//调用过滤条件
                    {
                        acp.Conditions.ConditionType = parameterNode.GetXmlNodeAttributeValue("ConditionType", "AND").ToEnum_<ConditionType>();
                        var conditionList = parameterNode.ChildNodes;
                        if (conditionList != null)
                        {
                            foreach (System.Xml.XmlNode conditionNode in conditionList)
                            {
                                var condition = new ExecCondition(conditionNode);
                                if (condition.FiledPath.IsNullOrEmpty())
                                {
                                    msg = apiError + " 的 <Condition FiledPath属性不能为空";
                                    return Tuple.Create(false, acp);
                                }
                                if (condition.Operand.IsNullOrEmpty())
                                {
                                    msg = apiError + " 的 <Condition Operand属性不能为空";
                                    return Tuple.Create(false, acp);
                                }
                                acp.Conditions.Add(condition);
                            }
                        }
                    }
                    #endregion

                    #region Executor 下级执行者
                    else if (localName.Equals("Executor", StringComparison.OrdinalIgnoreCase))//下级执行者
                    {
                        var tacp = getExecutor(apiError, null, parameterNode, apiInfo, controller, out msg);
                        if (tacp.Item1 == false) return Tuple.Create(false, acp);
                        if (tacp.Item2 != null)
                        {
                            if (acp.NextExecutors == null)
                                acp.NextExecutors = new List<BaseExecutor>();
                            acp.NextExecutors.Add(tacp.Item2);
                        }
                    }
                    #endregion
                }
            }
            #endregion

            return Tuple.Create(true, acp);
        }
        protected bool setInput(BaseExecutor acp, string apiError, System.Xml.XmlNode inputNode, ApiInfo apiInfo, out string msg)
        {
            msg = "";
            if (inputNode.NodeType == System.Xml.XmlNodeType.Comment)// 判断等于注释时
            {
                return true;
            }
            var localName = inputNode.LocalName;
            #region input 入参
            if (localName.ToLower() == "input")//入参
            {
                var parameter = new ApiFieldInfo(inputNode);
                if (parameter.Name.IsNullOrEmpty())
                {
                    msg = apiError + " 的 <Parameter Name属性不能为空";
                    return false;
                }
                if (acp.ApiInputInfoList == null) acp.ApiInputInfoList = new List<ApiFieldInfo>();
                if (acp.ApiInputInfoList.Exists(f => f.Name.Equals(parameter.Name)))
                {
                    acp.ApiInputInfoList.RemoveAll(f => f.Name.Equals(parameter.Name));
                    //msg = $"{apiError} 的 <Parameter Name={apiInfo.ApiName}/>入参字段名称重复";
                    //return false;
                }

                acp.ApiInputInfoList.Add(parameter);

                var ret = setSubField("Parameter", apiError, inputNode, parameter, out msg);
                if (ret == false) return false;
            }
            #endregion
            return true;
        }
        protected bool setOutput(SqlTplExecutor sqlTpl, string apiError, System.Xml.XmlNode outputNode, ApiInfo apiInfo, out string msg)
        {
            msg = "";
            #region OutputInfo
            if (outputNode.NodeType == System.Xml.XmlNodeType.Comment)// 判断等于注释时
            {
                return true;
            }
            #region Output
            var output = new ApiOutputInfo(outputNode);
            output.ApiName = apiInfo.ApiName;
            if (output.OutputName.IsNullOrEmpty())
            {
                msg = apiError + " 的 <Output OutputName属性不能为空";
                return false;
            }
            if (sqlTpl.OutputList == null) sqlTpl.OutputList = new List<ApiOutputInfo>();
            if (sqlTpl.OutputList.Exists(f => f.OutputName.Equals(output.OutputName)))
            {
                sqlTpl.OutputList.RemoveAll(f => f.OutputName.Equals(output.OutputName));
                //msg = $"{apiError} 的 <Output OutputName={output.OutputName}/>出参名称重复";
                //return true;
            }

            sqlTpl.OutputList.Add(output);
            #endregion

            #region FieldInfo
            var fieldInfoList = outputNode.ChildNodes;
            if (fieldInfoList != null)
            {
                output.ApiInputInfoList = new List<ApiFieldInfo>();
                foreach (System.Xml.XmlNode fieldInfoNode in fieldInfoList)
                {
                    if (fieldInfoNode.NodeType == System.Xml.XmlNodeType.Comment)// 判断等于注释时
                    {
                        continue;
                    }
                    var fieldInfo = new ApiFieldInfo(fieldInfoNode);
                    if (fieldInfo.Name.IsNullOrEmpty())
                    {
                        msg = $"{apiError } OutputName={output.OutputName} 的 <FieldInfo Name属性不能为空";
                        return false;
                    }
                    if (output.ApiInputInfoList.Exists(f => f.Name.Equals(fieldInfo.Name)))
                    {
                        output.ApiInputInfoList.RemoveAll(f => f.Name.Equals(fieldInfo.Name));

                        //msg = $"{apiError} OutputName={output.OutputName} 的 <FieldInfo Name={apiInfo.ApiName}/>出参实体的字段名称重复";
                        //return false;
                    }
                    output.ApiInputInfoList.Add(fieldInfo);

                    var ret = setSubField("FieldInfo", apiError, fieldInfoNode, fieldInfo, out msg);
                    if (ret == false) return false;
                }
            }
            #endregion
            #endregion

            return true;
        }
        /// <summary>
        /// 获取字段子节点
        /// </summary>
        /// <param name="apiError"></param>
        /// <param name="fieldNode"></param>
        /// <param name="pfieldNode"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        protected bool setSubField(string name, string apiError, System.Xml.XmlNode fieldNode, ApiFieldInfo pfieldNode, out string msg)
        {
            msg = "";
            var parameterList = fieldNode.ChildNodes;
            if (parameterList != null)
            {
                #region SubFieldInfoList
                pfieldNode.SubFieldInfoList = new List<ApiFieldInfo>();
                foreach (System.Xml.XmlNode parameterNode in parameterList)
                {
                    if (parameterNode.NodeType == System.Xml.XmlNodeType.Comment)// 判断等于注释时
                    {
                        continue;
                    }
                    var parameter = new ApiFieldInfo(parameterNode);
                    if (parameter.Name.IsNullOrEmpty())
                    {
                        msg = apiError + " 的 <{name} Name属性不能为空";
                        return false;
                    }
                    if (pfieldNode.SubFieldInfoList.Exists(f => f.Name.Equals(parameter.Name)))
                    {
                        msg = $"{apiError} 的 <{name} Name={pfieldNode.Name}/>子节点字段名称重复";
                        return false;
                    }

                    pfieldNode.SubFieldInfoList.Add(parameter);

                    var ret = setSubField(name, apiError, parameterNode, parameter, out msg);
                    if (ret == false) return false;
                }
                #endregion
            }
            return true;
        }

        //---------------------------------------------------------------------------------------------------------------------------------------------------
        protected bool setInput(BaseExecutor acp, string apiError, Newtonsoft.Json.Linq.JToken inputNode, ApiInfo apiInfo, out string msg)
        {
            msg = "";
            if (inputNode == null)// 判断等于注释时
            {
                return true;
            }
            #region input 入参
            var parameter = new ApiFieldInfo(inputNode);
            if (parameter.Name.IsNullOrEmpty())
            {
                msg = apiError + " 的 <Parameter Name属性不能为空";
                return false;
            }
            if (acp.ApiInputInfoList == null) acp.ApiInputInfoList = new List<ApiFieldInfo>();
            if (acp.ApiInputInfoList.Exists(f => f.Name.Equals(parameter.Name)))
            {
                acp.ApiInputInfoList.RemoveAll(f => f.Name.Equals(parameter.Name));
                //msg = $"{apiError} 的 <Parameter Name={apiInfo.ApiName}/>入参字段名称重复";
                //return false;
            }

            acp.ApiInputInfoList.Add(parameter);

            var ret = setSubField("Parameter", apiError, inputNode, parameter, out msg);
            if (ret == false) return false;
            #endregion
            return true;
        }
        protected bool setOutput(SqlTplExecutor sqlTpl, string apiError, Newtonsoft.Json.Linq.JToken outputNode, ApiInfo apiInfo, out string msg)
        {
            msg = "";
            #region OutputInfo
            if (outputNode==null)// 判断等于注释时
            {
                return true;
            }
            #region Output
            var output = new ApiOutputInfo(outputNode);
            output.ApiName = apiInfo.ApiName;
            if (output.OutputName.IsNullOrEmpty())
            {
                msg = apiError + " 的 <Output OutputName属性不能为空";
                return false;
            }
            if (sqlTpl.OutputList == null) sqlTpl.OutputList = new List<ApiOutputInfo>();
            if (sqlTpl.OutputList.Exists(f => f.OutputName.Equals(output.OutputName)))
            {
                sqlTpl.OutputList.RemoveAll(f => f.OutputName.Equals(output.OutputName));
                //msg = $"{apiError} 的 <Output OutputName={output.OutputName}/>出参名称重复";
                //return true;
            }

            sqlTpl.OutputList.Add(output);
            #endregion

            #region FieldInfo
            var fieldInfoList = outputNode.Value<Newtonsoft.Json.Linq.JArray>("ApiInputInfoList");
            if (fieldInfoList != null)
            {
                output.ApiInputInfoList = new List<ApiFieldInfo>();
                foreach (var fieldInfoNode in fieldInfoList)
                {
                    if (fieldInfoNode==null)// 判断等于注释时
                    {
                        continue;
                    }
                    var fieldInfo = new ApiFieldInfo(fieldInfoNode);
                    if (fieldInfo.Name.IsNullOrEmpty())
                    {
                        msg = $"{apiError } OutputName={output.OutputName} 的 <FieldInfo Name属性不能为空";
                        return false;
                    }
                    if (output.ApiInputInfoList.Exists(f => f.Name.Equals(fieldInfo.Name)))
                    {
                        output.ApiInputInfoList.RemoveAll(f => f.Name.Equals(fieldInfo.Name));

                        //msg = $"{apiError} OutputName={output.OutputName} 的 <FieldInfo Name={apiInfo.ApiName}/>出参实体的字段名称重复";
                        //return false;
                    }
                    output.ApiInputInfoList.Add(fieldInfo);

                    var ret = setSubField("FieldInfo", apiError, fieldInfoNode, fieldInfo, out msg);
                    if (ret == false) return false;
                }
            }
            #endregion
            #endregion

            return true;
        }
        /// <summary>
        /// 获取字段子节点
        /// </summary>
        /// <param name="apiError"></param>
        /// <param name="fieldNode"></param>
        /// <param name="pfieldNode"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        protected bool setSubField(string name, string apiError, Newtonsoft.Json.Linq.JToken fieldNode, ApiFieldInfo pfieldNode, out string msg)
        {
            msg = "";
            var parameterList = fieldNode.Value<Newtonsoft.Json.Linq.JArray>("SubFieldInfoList");
            if (parameterList != null)
            {
                #region SubFieldInfoList
                pfieldNode.SubFieldInfoList = new List<ApiFieldInfo>();
                foreach (var parameterNode in parameterList)
                {
                    if (parameterNode==null)// 判断等于注释时
                    {
                        continue;
                    }
                    var parameter = new ApiFieldInfo(parameterNode);
                    if (parameter.Name.IsNullOrEmpty())
                    {
                        msg = apiError + " 的 <{name} Name属性不能为空";
                        return false;
                    }
                    if (pfieldNode.SubFieldInfoList.Exists(f => f.Name.Equals(parameter.Name)))
                    {
                        msg = $"{apiError} 的 <{name} Name={pfieldNode.Name}/>子节点字段名称重复";
                        return false;
                    }

                    pfieldNode.SubFieldInfoList.Add(parameter);

                    var ret = setSubField(name, apiError, parameterNode, parameter, out msg);
                    if (ret == false) return false;
                }
                #endregion
            }
            return true;
        }
        #endregion
        protected void showException(string msg)
        {
            throw new System.Exception("LoadApiControllers Error:" + msg);
        }
    }
}
